#include "Socket.h"


Socket::Socket(int socket, socketType type):
addrlen(sizeof(sockaddr_in)), socketfd(socket), type(type)
{
}

Socket::Socket():
addrlen(sizeof(sockaddr_in)), socketfd(-1), type(CLIENT_SOCKET)
{
}

int Socket::Accept()
{
    if(socketfd == -1) 
        return -1;
    if(type == CLIENT_SOCKET) 
        return -1;
    return accept(socketfd, (struct sockaddr*)&addr, &addrlen);
}

/*
return: 
    -1: Error happens.
    0 : Connection lost.
    others(>0): The length of received bytes

*/
int Socket::Recv(void* buffer, int length)
{
    if(socketfd == -1){ 
        return -1;
    }
    if(type == SERVER_SOCKET){
        return -1;
    }
    return recv(socketfd,buffer,length, 0); //non-blocking recv()
}

int Socket::Send(void* buffer, int bytes)
{
    if(socketfd == -1){ 
        return -1;
    }
    if(type == SERVER_SOCKET){
        return -1;
    }
    return send(socketfd, buffer, bytes, 0); //non-blocking recv()
}

bool Socket::Close()
{
    if(socketfd == -1) return true;
    return close(socketfd) == -1? false : true;
}

void Socket::changeSocket(int socket, socketType type)
{
    this->socketfd = socket;
    this->type = type;
}

sockaddr_in Socket::getAddr()
{
    return addr;
}
/*
flags: 1->Non-blocking
       0->Blocking(default)
*/
int Socket::initListenSocket(string IPV4_addr, int port, int nfds , int flags)
{
    int listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(listen_sock < 0) return -1;
    if(flags == 1) setNonblockingSocket(listen_sock);
    sockaddr_in serverSock;
    memset(&serverSock, 0, sizeof(serverSock));
    serverSock.sin_family = AF_INET;
    serverSock.sin_addr.s_addr = inet_addr(IPV4_addr.c_str());
    serverSock.sin_port = htons(port);
    if(bind(listen_sock, (sockaddr*)&serverSock,sizeof(serverSock)) < 0) 
        return -1;
    if(listen(listen_sock,nfds) < 0)
        return -1;
    return listen_sock;	
}

bool Socket::setNonblockingSocket(int socket)
{
    int flags = fcntl(socket, F_GETFL, 0);
    fcntl(socket, F_SETFL, flags|O_NONBLOCK);
}

//获取socketfd
int Socket::getSocketfd()
{
    return this->socketfd;
}

//获取错误代号
int Socket::getErrorno()
{
    return errno;
}

socklen_t Socket::getAddrLen()
{
    return addrlen;
}